﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using t_205_verk_hopur_12.Models;
using t_205_verk_hopur_12.Helpers;
using System.Web.Security;
using t_205_verk_hopur_12.Authorize;
using System.Web.Routing;

namespace t_205_verk_hopur_12.Models
{
    public class ChannelController : Controller
    {
        public IChannelRepository channelRepo { get; set; }
        public IUserRepository userRepo { get; set; }
        public ICategoryRepository catRepo { get; set; }
        public IVideoRepository videoRepo { get; set; }
        public IScheduleRepository scheduleRepo { get; set; }

        public ITool toolkit { get; set; }

        protected override void Initialize(RequestContext requestContext)
        {
            if (toolkit == null) { toolkit = new Tool(); }
            if (channelRepo == null) { channelRepo = new ChannelRepository(); }
            if (userRepo == null) { userRepo = new UserRepository(); }
            if (catRepo == null) { catRepo = new CategoryRepository(); }
            if (videoRepo == null) { videoRepo = new VideoRepository(); }
            if (scheduleRepo == null) { scheduleRepo = new ScheduleRepository(); }

            base.Initialize(requestContext);
        }
        //
        // GET: /Channel/
        public ActionResult Index(int? id, int? scheduleID)
        {
            if (id.HasValue)
            {
                int channelID = id.Value;
                User currentUser = toolkit.GetCurrentUser();
                Channel thisChannel = channelRepo.GetChannelByID(channelID);
                
                // Channel id does not exist
                if (thisChannel == null)
                {
                    return View("NotFound");
                }

                User channelOwner = userRepo.GetUserByID(thisChannel.OwnerID);
                Category channelCategory = catRepo.GetSingleCategory(thisChannel.CategoryID);
                ScheduleVideo currentSchedule;

                IQueryable<ScheduleVideo> schedule;
                IQueryable<ScheduleVideo> topVideos = videoRepo.GetPopularVideoByChannel(thisChannel.ID);
                IQueryable<Announcement> announcements = channelRepo.GetAnnouncementsByID(channelID);

                bool userVotedChannel;
                bool userVotedVideo = false;
                bool isOwnerOrEmployee;
                bool isSubscribedToChannel;
                bool hasApplied;

                // If the user wants to watch a specific schedule item
                if (scheduleID.HasValue)
                {
                    currentSchedule = scheduleRepo.getScheduleById(scheduleID.Value);

                    // Invalid schedule ID
                    if (currentSchedule == null)
                    {
                        return View("NotFound");
                    }

                    // case of youtube video
                    if (currentSchedule.Embed.Contains("youtube"))
                    {
                        EmbedBuilder newEmbed = new EmbedBuilder(currentSchedule.Embed);
                        currentSchedule.Embed = newEmbed.GetEmbedCode();
                    }
                }
                else
                {
                    currentSchedule = scheduleRepo.GetCurrentScheduleVideoByID(thisChannel.ID);

                    if(currentSchedule != null)
                    {
                        if (currentSchedule.Embed.Contains("youtube"))
                        {
                            EmbedBuilder newEmbed = new EmbedBuilder(currentSchedule.Embed);
                            currentSchedule.Embed = newEmbed.GetEmbedCode();
                        }
                    }
                }

                // If there is a logged in user
                if (currentUser != null)
                {
                    userVotedChannel = channelRepo.HasUserVotedChannel(new ChannelVote { ChannelID = thisChannel.ID, UserId = currentUser.ID });
                    isOwnerOrEmployee = channelRepo.IsOwnerOrEmployee(currentUser.ID, thisChannel.ID);
                    isSubscribedToChannel = channelRepo.IsSubscribed(currentUser.ID, thisChannel.ID);
                    hasApplied = channelRepo.HasApplied(currentUser.ID, thisChannel.ID);
                }
                else
                {
                    userVotedChannel = false;
                    isOwnerOrEmployee = false;
                    isSubscribedToChannel = false;
                    hasApplied = false;
                }

                if (currentSchedule != null)
                {
                    if (currentUser != null)
                    {
                        userVotedVideo = videoRepo.HasUserVotedVideo(new VideoVote { UserID = currentUser.ID, VideoID = currentSchedule.VideoID });
                    }

                    schedule = scheduleRepo.GetScheduleByDay(thisChannel.ID, currentSchedule.StartTime);
                }
                else
                {
                    schedule = null;
                }

                return View(new ChannelIndexViewModel(thisChannel, channelOwner,
                                                      channelCategory, currentSchedule, 
                                                      schedule, userVotedChannel,
                                                      isOwnerOrEmployee, isSubscribedToChannel, 
                                                      hasApplied, userVotedVideo,
                                                      announcements, topVideos));
            }

            return View("NotFound");  // If no videoID was input          
        }

        // GET: /Channel/Create 
        // Displays form for creating a new channel
        [Authorize]
        public ActionResult Create()
        {
            Channel newChannel = new Channel();
            var categories = catRepo.GetAllCategories();

            var selectList = new SelectList(categories, "ID", "Name");
            ViewData["SelectList"] = selectList;

            return View(new ChannelFormViewModel(newChannel, categories));
        }

        // POST: /Channel/Create
        [Authorize]
        [HttpPost]
        public ActionResult Create(ChannelFormViewModel newChannel)
        {
            var categories = catRepo.GetAllCategories();

            var selectList = new SelectList(categories, "ID", "Name", newChannel.Channel.CategoryID);
            ViewData["SelectList"] = selectList;

            if (ModelState.IsValid)
            {
                var currentUser = toolkit.GetCurrentUser();
                
                try
                {
                    newChannel.Channel.OwnerID = currentUser.ID;

                    channelRepo.Add(newChannel.Channel);
                    channelRepo.Save();

                    return RedirectToAction("Admin", "Channel", new { id = newChannel.Channel.ID }); // Add detail view, user should be routed to next step
                }

                catch
                {
                   ModelState.AddRuleViolations(newChannel.Channel.GetRuleViolations());
                }
            }

            return View(new ChannelFormViewModel(newChannel.Channel, newChannel.Category));
        }


        // To edit a channel
        [ChannelOwnerAuthorize]
        [HttpGet]
        public ActionResult Edit(int? id)
        {
            var categories = catRepo.GetAllCategories();
            var currentUser = toolkit.GetCurrentUser();
            
            if (id.HasValue)
            {
                Channel currentChannel = channelRepo.GetChannelByID(id.Value);
                
                var selectList = new SelectList(categories, "ID", "Name", currentChannel.CategoryID);
                ViewData["SelectList"] = selectList;

                ChannelFormViewModel vm = new ChannelFormViewModel(currentChannel, categories);

                if (currentChannel.OwnerID != currentUser.ID) // so only the owner can edit
                {
                    return View("NotAuthorized");
                }
                else
                {
                    return View(vm);
                }
            }

            return View("NotFound");
        }

        [ChannelOwnerAuthorize]
        [HttpPost]
        public ActionResult Edit(ChannelFormViewModel newChannel)
        {
            var categories = catRepo.GetAllCategories();

            var selectList = new SelectList(categories, "ID", "Name", newChannel.Channel.CategoryID);
            ViewData["SelectList"] = selectList;

            if (ModelState.IsValid)
            {
                try
                {
                    UpdateModel(newChannel.Channel);

                    var currentUser = toolkit.GetCurrentUser();
                    Channel currentChannel = channelRepo.GetChannelByID(newChannel.Channel.ID);

                    currentChannel.ID = newChannel.Channel.ID;
                    currentChannel.OwnerID = currentUser.ID;
                    currentChannel.Name = newChannel.Channel.Name;
                    currentChannel.Description = newChannel.Channel.Description;
                    currentChannel.Autocracy = newChannel.Channel.Autocracy;
                    currentChannel.CategoryID = newChannel.Channel.CategoryID;

                    channelRepo.Save();

                    return RedirectToAction("Index", new { id = newChannel.Channel.ID });
                }

                catch
                {
                    ModelState.AddRuleViolations(newChannel.Channel.GetRuleViolations());
                }
            }

            return View(new ChannelFormViewModel(newChannel.Channel, categories));
        }

        [HttpGet]
        public ActionResult Search(string query, string sort, string by)
        {
            var searchResults = channelRepo.GetSearchResults(query, sort, by);

            return View(searchResults);
        }

        
        // To get the week schedule of a particular channel
        public ActionResult Schedule(int? id, DateTime? day)
        {
            if (id.HasValue)
            {
                Channel currentChannel = channelRepo.GetChannelByID(id.Value);

                if (currentChannel == null)
                {
                    return View("NotFound");
                }

                User currentUser = toolkit.GetCurrentUser();
                List<IQueryable<ScheduleVideo>> week = new List<IQueryable<ScheduleVideo>>(); // videos on each day of the week
                IQueryable<ScheduleVideo> dayOfVideos;
                DateTime firstDayOfWeek = new DateTime();
                DateTime dayOfLastWeek = new DateTime();
                DateTime dayOfNextWeek = new DateTime();
                bool isOwner = false;

                if (currentUser != null)
                {
                    isOwner = (currentUser.ID == currentChannel.OwnerID);
                }

                if (!day.HasValue)
                {
                    firstDayOfWeek = DateTime.Now.StartOfWeek(DayOfWeek.Monday); // Helper class
                }
                else
                {
                    firstDayOfWeek = day.Value.StartOfWeek(DayOfWeek.Monday);
                }

                dayOfLastWeek = firstDayOfWeek.Subtract(new TimeSpan(7, 0, 0, 0, 0));
                dayOfNextWeek = firstDayOfWeek.AddDays(7);


                // To insert the videos of each day
                for (int i = 0; i < 7; i++)
                {
                    dayOfVideos = scheduleRepo.GetScheduleByDay(id.Value, firstDayOfWeek);
                    week.Add(dayOfVideos);
                    firstDayOfWeek = firstDayOfWeek.AddDays(1);
                }

                return View(new ScheduleIndexViewModel(currentChannel, week,
                                                       firstDayOfWeek, dayOfLastWeek,
                                                       dayOfNextWeek, isOwner));
            }

            // No id in url
            return View("NotFound");
        }

        // To edit the channel schedule
        [ChannelOwnerAuthorize]
        public ActionResult EditSchedule(int channelID, DateTime? day, int? scheduleID)
        {
            User currentuser = toolkit.GetCurrentUser();
            Channel currentChannel = channelRepo.GetChannelByID(channelID);
            IQueryable<ScheduleVideo> dayOfVideos;
            IQueryable<Video> videos = videoRepo.GetApprovedVideosByChannelID(channelID);
            ScheduleVideo selectedSchedule;
            SelectList selectList;
            DateTime now;
            DateTime yesterday;
            DateTime tomorrow;

            if (scheduleID.HasValue)
            {
                selectedSchedule = scheduleRepo.getScheduleById(scheduleID.Value);
                selectList = new SelectList(videos, "ID", "Title", selectedSchedule.VideoID);
            }
            else
            {
                selectedSchedule = null;
                selectList = new SelectList(videos, "ID", "Title");
            }

            ViewData["SelectList"] = selectList;

            if (day.HasValue)
            {
                dayOfVideos = scheduleRepo.GetScheduleByDay(channelID, day.Value);
                now = day.Value;
                yesterday = day.Value.Subtract(new TimeSpan(1, 0, 0, 0, 0));
                tomorrow = day.Value.AddDays(1);
            }
            else
            {
                dayOfVideos = scheduleRepo.GetScheduleByDay(channelID, DateTime.Now);
                now = DateTime.Now;
                yesterday = now.Subtract(new TimeSpan(1, 0, 0, 0));
                tomorrow = now.AddDays(1);
            }
            
            return View(new EditScheduleViewModel(currentChannel, 
                                                  dayOfVideos, videos, selectedSchedule,
                                                  now, yesterday, tomorrow));
        }

        [ChannelOwnerAuthorize]
        [HttpPost]
        public ActionResult EditSchedule(int channelID, DateTime? day, FormCollection form, int? scheduleID)
        {
            // Get the form values
            int videoID = System.Convert.ToInt32(form["ScheduleVideo"].ToString());
            DateTime startTime;
            DateTime endTime;

            if (day.HasValue)
            {
                startTime = new DateTime(day.Value.Year, day.Value.Month, day.Value.Day);
                endTime = new DateTime(day.Value.Year, day.Value.Month, day.Value.Day);
            }
            else
            {
                startTime = DateTime.Now.Date;
                endTime = DateTime.Now.Date;
            }

            startTime = startTime.AddHours(System.Convert.ToInt32(form["fromHour"].ToString()));
            startTime = startTime.AddMinutes(System.Convert.ToInt32(form["fromMinute"].ToString()));

            endTime = endTime.AddHours(System.Convert.ToInt32(form["toHour"].ToString()));
            endTime = endTime.AddMinutes(System.Convert.ToInt32(form["toMinute"].ToString()));

            // we check for overlapping with other schedule items
            bool endTimeCheck = (startTime < endTime);
            bool isOverlap = scheduleRepo.CheckForOverlapInSchedule(channelID, (scheduleID.HasValue ? scheduleID.Value : 0), startTime, endTime);

            // Then we are editing, else we are adding
            if (scheduleID.HasValue)
            {
                if (endTimeCheck && !isOverlap)
                {
                    Schedule editSchedule = scheduleRepo.getScheduleItemById(scheduleID.Value);

                    editSchedule.VideoID = videoID;
                    editSchedule.StartTime = startTime;
                    editSchedule.EndTime = endTime;

                    UpdateModel(editSchedule);
                    scheduleRepo.Save();
                }

                if (day.HasValue)
                {
                    return RedirectToAction("EditSchedule", "Channel", new { channelID = channelID, day = day.Value.ToString("yyyy-M-dd") });
                }

                return RedirectToAction("EditSchedule", "Channel", new { channelID = channelID });
            }

            // End time is after start time and 
            // we check for overlapping with other schedule items
            if(endTimeCheck && !isOverlap)
            {
                scheduleRepo.AddToSchedule(channelID, videoID, startTime, endTime);
                
                // To change the state of the video to played (4);
                Video addedVideo = videoRepo.GetVideoByID(videoID);
                addedVideo.State = 4;

                if (day.HasValue)
                {
                    return RedirectToAction("EditSchedule", "Channel", new { channelID = channelID, day = day.Value.ToString("yyyy-M-dd") });
                }

                return RedirectToAction("EditSchedule", "Channel", new { channelID = channelID });
            }

            if (day.HasValue)
            {
                return RedirectToAction("EditSchedule", "Channel", new { channelID = channelID, day = day.Value.ToString("yyyy-M-dd") });
            }

            return RedirectToAction("EditSchedule", "Channel", new { channelID = channelID });
        }

        // Removes a schedule item from the schedule
        [ChannelOwnerAuthorize]
        [HttpGet]
        public ActionResult DeleteSchedule(int id, DateTime day, int scheduleID)
        {
            ScheduleVideo deleteVideo = scheduleRepo.getScheduleById(scheduleID);
            Channel currentChannel = channelRepo.GetChannelByID(id);

            return View(new DeleteScheduleViewModel(deleteVideo, currentChannel));
        }

        // Removes a schedule item from the schedule
        [ChannelOwnerAuthorize]
        [HttpPost]
        public ActionResult DeleteSchedule(int id, DateTime day, int scheduleID, FormCollection form)
        {
            try
            {
                scheduleRepo.DeleteSchedule(scheduleID);
            }

            catch
            {
                // Error redirect
                return RedirectToAction("DeleteSchedule", "Channel", new { id = id, scheduleID = scheduleID, day = day.ToString("yyyy-MM-dd") });
            }

            // Success redirect
            return RedirectToAction("EditSchedule", "Channel", new { channelID = id, day = day.ToString("yyyy-MM-dd"), scheduleID = "" });
        }

        // To implement Channel voting
        [Authorize]
        [HttpPost]
        public string VoteChannel(int channelID, int vote)
        {
            channelRepo.VoteChannel(channelID, vote);
            return "<img src='/Content/Icons/information.png' alt='Takk fyrir að kjósa' title='Takk fyrir að kjósa' /> Takk fyrir að kjósa";
        }

        // Displays the Control Page for channel owner
        [OwnerOrEmployeeAuthorize]
        public ActionResult Admin(int id)
        {
            User currentUser = toolkit.GetCurrentUser();
            Channel currentChannel = channelRepo.GetChannelByID(id);
            bool isEmployee = channelRepo.IsEmployee(currentUser.ID, id);
            bool isOwner = currentChannel.OwnerID == currentUser.ID;

            return View(new AdminMenuViewModel(channelRepo.GetChannelByID(id), isOwner, isEmployee));
        }

        // Displays all Notices for channel
        [ChannelOwnerAuthorize]
        public ActionResult Notice(int id)
        {
            var curUser = toolkit.GetCurrentUser();
            Channel ch = channelRepo.GetChannelByID(id);
            IEnumerable<Announcement> notices = channelRepo.GetAnnouncementsByID(id);

            if (curUser.ID == ch.OwnerID)
            {
                return View(new ChannelNoticeViewModel(ch, notices));
            }
            else
            {
                return View("NotAuthorized");
            }
        }

        // GET: Channel/NoticeCreate
        // Creates new announcements(notices) for channel
        [ChannelOwnerAuthorize]
        [HttpGet]
        public ActionResult NoticeCreate(int id)
        {
            Announcement newNote = new Announcement();
            Channel Channel = channelRepo.GetChannelByID(id);

            return View(new ChannelNoticeViewModel(Channel, newNote));
        }

        // POST: /Channel/NoticeCreate
        // Committs the new announcement(notice) in database
        [ChannelOwnerAuthorize]
        [HttpPost]
        public ActionResult NoticeCreate(ChannelNoticeViewModel newNote, int id)
        {
            newNote.Channel = channelRepo.GetChannelByID(id);
            newNote.Announcement.ChannelID = id;

            if (ModelState.IsValid)
            {
                newNote.Announcement.CreationDate = DateTime.Now;
                channelRepo.AddAnnouncements(newNote.Announcement);
                channelRepo.Save();

                return RedirectToAction("Notice", "Channel", new { id = id });
            }

            return View(newNote);
        }

        // Add video to the channel's collection ofvideos
        [OwnerOrEmployeeAuthorize]
        [HttpGet]
        public ActionResult AddVideo(int? id)
        {
            if(id.HasValue)
            {
                ChannelVideoViewModel newVideo = new ChannelVideoViewModel();
                newVideo.Channel = channelRepo.GetChannelByID(id.Value);

                return View(newVideo);
            }

            return View("NotFound");
        }

        // POST: /Channel/AddVideo/
        [OwnerOrEmployeeAuthorize]
        [HttpPost]
        [ValidateInput(false)]
        public ActionResult AddVideo(int id, ChannelVideoViewModel newVideo)
         {
             newVideo.Channel = channelRepo.GetChannelByID(id);

             if (ModelState.IsValid)
             {
                 try
                 {
                     var currentUser = toolkit.GetCurrentUser();
                     newVideo.SingleVideo.UserID = currentUser.ID;
                     newVideo.SingleVideo.ChannelID = id;
                     newVideo.SingleVideo.State = 0;
                     newVideo.SingleVideo.Rating = 0;
                     newVideo.SingleVideo.SubmittedByUser = false;
                     newVideo.SingleVideo.ID = 0;

                     videoRepo.AddVideo(newVideo.SingleVideo);
                     videoRepo.Save();
                     return RedirectToAction("Videos", "Channel", new { id = id });
                 }

                 catch
                 {
                     // TODO: Need to implement newVideo.Videos.GetRuleViolations()
                 }
             }

             return View(newVideo);
         }

        // GET: /Channel/NoticeEdit
        // Edits existing announcement(notice)
        [ChannelOwnerAuthorize]
        [HttpGet]
        public ActionResult NoticeEdit(int channelID, int noteID)
        {
            ChannelNoticeViewModel editNote = new ChannelNoticeViewModel();
            
            editNote.Announcement = channelRepo.GetAnnouncementByAnnouncementID(noteID);
            editNote.Channel = channelRepo.GetChannelByID(channelID);

            return View(editNote);
        }

        //POST: /Channel/NoticeEdit
        // Committs the changes to announcement(notice) to the database
        [ChannelOwnerAuthorize]
        [HttpPost]
        public ActionResult NoticeEdit(int channelID, int noteID, ChannelNoticeViewModel editNote)
        {
            editNote.Channel = channelRepo.GetChannelByID(channelID);

            if (ModelState.IsValid)
            {
                Announcement currentNote = channelRepo.GetAnnouncementByAnnouncementID(noteID);
                currentNote.Title = editNote.Announcement.Title;
                currentNote.Body = editNote.Announcement.Body;

                try
                {
                    UpdateModel(currentNote);
                    channelRepo.Save();
                }

                catch
                {
                    ModelState.AddRuleViolations(editNote.Channel.GetRuleViolations());
                }

                return RedirectToAction("Notice", "Channel", new { id = channelID });
            }

            return View(editNote);
        }

        // GET: /Channel/Election
        // Displays a list of elections on channel
        [OwnerOrEmployeeAuthorize]
        [HttpGet]
        public ActionResult Election(int id)
        {
            User currentUser = toolkit.GetCurrentUser();

            ChannelElectionViewModel channelElection = new ChannelElectionViewModel();
            channelElection.Channel = channelRepo.GetChannelByID(id);
            channelElection.Elections = channelRepo.GetElectionsByChannelId(id, currentUser.ID);
            channelElection.Videos = channelRepo.GetVideoInElectionState(id);

            return View(channelElection);
        }

        // POST: /Channel/Election
        // Committs election to database
        [OwnerOrEmployeeAuthorize]
        [HttpPost]
        public ActionResult Election(int id, FormCollection votes)
        {
            Channel ch = channelRepo.GetChannelByID(id);
            Dictionary<int, int> FormResults = new Dictionary<int, int>();
            User user = toolkit.GetCurrentUser();

            foreach(string x in votes.Keys)
            {
                int key = System.Convert.ToInt32(x, 10);
                int value = System.Convert.ToInt32(votes[x], 10);

                FormResults.Add(key, value);
            }

            if (ModelState.IsValid)
            {
                try
                {
                    foreach (var x in FormResults)
                    {
                        channelRepo.SaveElectionByUserId(user.ID, x.Key, x.Value);
                    }
                    
                    return RedirectToAction("Index");
                }

                catch
                {
                    // Implement a error solution
                    return View("Error");
                }
            }
            
            return View(new ChannelElectionViewModel(channelRepo.GetChannelByID(id),
                                                     channelRepo.GetElectionsByChannelId(id, user.ID),
                                                     channelRepo.GetVideoInElectionState(id)));
        }

        // POST: /Channel/ElectionCreate
        // Committs a new election into database
        [ChannelOwnerAuthorize]
        [HttpGet]
        public ActionResult ElectionCreate(int id, int videoID)
        {
            if (channelRepo.GetChannelByID(id).Autocracy == false)
            {
                // User doesn´t have permission
                // Only owner can create elections
                // Implement solution
                return View("Error");
            }

            VideoElection newElection = new VideoElection();

            newElection.ChannelID = id;
            newElection.VideoID = videoID;
            newElection.EndTime = DateTime.Now.AddHours(24);
            newElection.HasEnded = false;

            channelRepo.AddVideoToElection(newElection);

            return RedirectToAction("Videos", "Channel", new { id = id });
        }

        //POST: /Channel/ElectionEnd
        // Returns election results at channel owner behest
        [ChannelOwnerAuthorize]
        [HttpGet]
        public ActionResult ElectionEnd(int id, int videoID)
        {
            channelRepo.EndElection(id, videoID);

            return RedirectToAction("Videos", "Channel", new { id = id });
        }

        // List all videos in a given channel's repository
        [OwnerOrEmployeeAuthorize]
        public ActionResult Videos(int id)
        {
            ChannelVideoViewModel channelVideos = new ChannelVideoViewModel();
            User currUser = toolkit.GetCurrentUser();

            channelVideos.Channel = channelRepo.GetChannelByID(id);
            channelVideos.Video = videoRepo.GetVideosByChannelID(id);
            channelVideos.isOwner = channelVideos.Channel.OwnerID == currUser.ID;
            channelVideos.CurrentUser = toolkit.GetCurrentUser();

            return View(channelVideos);
        }

        // For a dictatorship channel to confirm an added video
        [ChannelOwnerAuthorize]
        public ActionResult ConfirmVideo(int id, int videoID)
        {
            Video stateChangedVideo = videoRepo.GetVideoByID(videoID);
            stateChangedVideo.State = 2;
            videoRepo.Save();

            return RedirectToAction("Videos", "Channel", new { id = id });
        }


        // Edit a video
        [Authorize]
        public ActionResult EditVideo(int channelID, int videoID)
        {
            ChannelVideoViewModel channelVideo = new ChannelVideoViewModel();
            channelVideo.SingleVideo = videoRepo.GetVideoByID(videoID);
            channelVideo.Channel = channelRepo.GetChannelByID(channelID);

            return View(channelVideo);
        }

        // Edit a video
        [Authorize]
        [HttpPost]
        [ValidateInput(false)]
        public ActionResult EditVideo(int channelID, int videoID, ChannelVideoViewModel newVideo)
        {
            newVideo.Channel = channelRepo.GetChannelByID(channelID);

            if (ModelState.IsValid)
            {
                Video tempVid = videoRepo.GetVideoByID(videoID);
                tempVid.Title = newVideo.SingleVideo.Title;
                tempVid.Description = newVideo.SingleVideo.Description;
                tempVid.Embed = newVideo.SingleVideo.Embed;

                try
                {
                    UpdateModel(tempVid);
                    videoRepo.Save();
                }
                catch
                {
                    return View("Error");
                }

                return RedirectToAction("Videos", "Channel", new { id = channelID });
            }

            return View(newVideo);
        }

        // To see video details
        [OwnerOrEmployeeAuthorize]
        public ActionResult VideoDetails(int id, int videoID)
        {
            ChannelVideoViewModel currVideo = new ChannelVideoViewModel();

            currVideo.SingleVideo = videoRepo.GetVideoByID(videoID);
            currVideo.Channel = channelRepo.GetChannelByID(id);
            currVideo.isOwner = toolkit.GetCurrentUser().ID == currVideo.Channel.OwnerID;

            return View(currVideo);
        }

        // Delete Video confirmation
        [ChannelOwnerAuthorize]
        [HttpGet]
        public ActionResult DeleteVideo(int id, int videoID)
        {
            ChannelVideoViewModel delVideo = new ChannelVideoViewModel();

            delVideo.SingleVideo = videoRepo.GetVideoByID(videoID);
            delVideo.Channel = channelRepo.GetChannelByID(id);

            return View(delVideo);
        }

        // POST for delete video
        [ChannelOwnerAuthorize]
        [HttpPost]
        public ActionResult DeleteVideo(int id, int videoID, ChannelVideoViewModel tempVideo)
        {
            Video channelVideo = videoRepo.GetVideoByID(videoID);

            videoRepo.Delete(channelVideo);
            videoRepo.Save();

            return RedirectToAction("Videos", "Channel", new { id = channelVideo.ChannelID });
        }

        // Allows user to subscribe to channel
        [Authorize]
        public string Subscribe(int id)
        {
            Subscription newSubscription = new Subscription();
            User x = toolkit.GetCurrentUser();

            newSubscription.UserID = toolkit.GetCurrentUser().ID;
            newSubscription.ChannelID = id;
            
            channelRepo.SubscribeToChannel(newSubscription);
            channelRepo.Save();
            
            return "<img src='/Content/Icons/information.png' alt='Takk fyrir að gerast áskrifandi' title='Takk fyrir að gerast áskrifandi' /> Takk fyrir að gerast áskrifandi<p>&nbsp;</p>";
        }

        // Allows user to unsubscribe to channel
        [Authorize]
        public string Unsubscribe(int id)
        {
            Subscription newSubscription = channelRepo.GetSubscriptionsByUserAndChannel(toolkit.GetCurrentUser().ID, id);

            channelRepo.UnsubscribeToChannel(newSubscription);
            channelRepo.Save();
            
            return "<img src='/Content/Icons/information.png' alt='Þú ert ekki lengur áskrifandi' title='Þú ert ekki lengur áskrifandi' /> Þú ert ekki lengur áskrifandi<p>&nbsp;</p>";
        }

        [Authorize]
        public string Apply(int id)
        {
            Application newApp = new Application();
            User x = toolkit.GetCurrentUser();

            newApp.UserID = toolkit.GetCurrentUser().ID;
            newApp.ChannelID = id;
            
            channelRepo.ApplyAtChannel(newApp);
            channelRepo.Save();
            
            return "<img src='/Content/Icons/information.png' alt='Takk fyrir að sækja um, umsóknin verður afgreidd eins fljótt og kostur gefst.' title='Takk fyrir að sækja um, umsóknin verður afgreidd eins fljótt og kostur gefst.' /> Takk fyrir að sækja um, umsóknin verður afgreidd eins fljótt og kostur gefst.";
        }

        // List all applications for a given channel
        [ChannelOwnerAuthorize]
        public ActionResult Applications(int? id)
        {
            if (id.HasValue)
            {
                ChannelApplicationViewModel cavm = new ChannelApplicationViewModel();

                cavm.Applications = channelRepo.GetApplicationsByChannelID(id.Value);
                cavm.Channel = channelRepo.GetChannelByID(id.Value);
                
                return View(cavm);
            }

            return View("NotFound");
        }
        // Remove an application from a list of applications
        [ChannelOwnerAuthorize]
        public ActionResult RemoveApplication(int id, int userID)
        {
            ChannelSingleApplicationViewModel csavm = new ChannelSingleApplicationViewModel();

            csavm.Applications = channelRepo.GetApplicationsByChannelID(id);
            csavm.Channel = channelRepo.GetChannelByID(id);
            csavm.IsOwnerOrEmployee = channelRepo.IsOwnerOrEmployee(userID, id);
            
            return View(csavm);
        }
        // POST: 
        [ChannelOwnerAuthorize]
        [HttpPost]
        public ActionResult RemoveApplication(int id, int userID, int? dummy)
        {

            Application app = channelRepo.GetApplicationByUserIdAndChannelId(userID, id);

            channelRepo.RemoveApplication(app);
            channelRepo.Save();
            
            return RedirectToAction("Applications", "Channel", new { id = id });
        }


        // Remove an application from a list of applications
        [ChannelOwnerAuthorize]
        public ActionResult HireEmployee(int id, int userID)
        {
            Application app = channelRepo.GetApplicationByUserIdAndChannelId(userID, id);

            return View(app);
        }

        // POST: 
        [ChannelOwnerAuthorize]
        [HttpPost]
        public ActionResult HireEmployee(int id, int userID, int? dummy)
        {
            Application app = channelRepo.GetApplicationByUserIdAndChannelId(userID, id);
            Permission pm = new Permission();

            pm.UserID = userID;
            pm.ChannelID = id;
            pm.Role = 1;
            
            channelRepo.HireEmployee(pm);
            channelRepo.RemoveApplication(app);
            channelRepo.Save();
            
            return RedirectToAction("Applications", "Channel", new { id = id });
        }


        // List all employees at a given channel
        [Authorize]
        public ActionResult Employees(int id)
        {
            ChannelEmployeesViewModel cevm = new ChannelEmployeesViewModel();

            cevm.Employees = channelRepo.GetEmployeesByChannelId(id);
            cevm.Channel = channelRepo.GetChannelByID(id);
            
            User currentUser = toolkit.GetCurrentUser();
            Channel thisChannel = channelRepo.GetChannelByID(id);

            if (currentUser != null)
            {
                cevm.HasAppliedToChannel = channelRepo.HasApplied(currentUser.ID, thisChannel.ID);
                cevm.IsOwnerOrEmployee = channelRepo.IsOwnerOrEmployee(currentUser.ID, thisChannel.ID);
                cevm.IsOwner = thisChannel.OwnerID == currentUser.ID;
            }
            else
            {
                cevm.HasAppliedToChannel = false;
                cevm.IsOwnerOrEmployee = false;
                cevm.IsOwner = false;
            }

            return View(cevm);
        }

        // Fire an employee
        [ChannelOwnerAuthorize]
        public ActionResult FireEmployee(int id, int userID)
        {
            Permission pm = channelRepo.GetPermissionByUserIdAndChannelId(userID, id);

            return View(pm);
        }

        // POST: 
        [ChannelOwnerAuthorize]
        [HttpPost]
        public ActionResult FireEmployee(int id, int userID, int? dummy)
        {
            Permission pm = channelRepo.GetPermissionByUserIdAndChannelId(userID, id);

            channelRepo.RevokePermission(pm);
            channelRepo.Save();
            
            return RedirectToAction("Employees", "Channel", new { id = id });
        }

        // To implement Video voting
        [Authorize]
        [HttpPost]
        public string VoteVideo(int videoID, int vote)
        {
            var currentUser = toolkit.GetCurrentUser();
            videoRepo.VoteVideo(videoID, currentUser.ID, vote);

            return "<img src='/Content/Icons/information.png' alt='Takk fyrir að kjósa' title='Takk fyrir að kjósa' /> Takk fyrir að kjósa";
        }
    }
}

//  __ __   ___   ____   __ __  ____       ______   ___   _      _____        ___  ____       ____     ___  _____ ______  __ __  ____  
// |  T  T /   \ |    \ |  T  T|    \     |      T /   \ | T    |     |      /  _]|    \     |    \   /  _]/ ___/|      T|  T  T|    \ 
// |  l  |Y     Y|  o  )|  |  ||  D  )    |      |Y     Y| |    |   __j     /  [_ |  D  )    |  o  ) /  [_(   \_ |      ||  |  ||  D  )
// |  _  ||  O  ||   _/ |  |  ||    /     l_j  l_j|  O  || l___ |  l_      Y    _]|    /     |     TY    _]\__  Tl_j  l_j|  |  ||    / 
// |  |  ||     ||  |   |  :  ||    \       |  |  |     ||     T|   _]     |   [_ |    \     |  O  ||   [_ /  \ |  |  |  |  :  ||    \ 
// |  |  |l     !|  |   l     ||  .  Y      |  |  l     !|     ||  T       |     T|  .  Y    |     ||     T\    |  |  |  l     ||  .  Y
// l__j__j \___/ l__j    \__,_jl__j\_j      l__j   \___/ l_____jl__j       l_____jl__j\_j    l_____jl_____j \___j  l__j   \__,_jl__j\_j                                                                                                                               
